package com.zzjson.netty.rpc.registry;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.codec.LengthFieldPrepender;
import io.netty.handler.codec.serialization.ClassResolvers;
import io.netty.handler.codec.serialization.ObjectDecoder;
import io.netty.handler.codec.serialization.ObjectEncoder;


/**
 * <p>****************************************************************************</p>
 * <p><b>Copyright © 2010-2020 shuncom team All Rights Reserved<b></p>
 * <ul style="margin:15px;">
 * <li>Description : com.zzjson.netty.rpc.registry</li>
 * <li>Version     : 1.0.0</li>
 * <li>Creation    : 2020年03月01日</li>
 * <li>@author     : zzy0_0</li>
 * </ul>
 * <p>****************************************************************************</p>
 */
public class RpcRegistry {
	private int port;

	public RpcRegistry(int port) {
		this.port = port;
	}


	public void start() {
		try {
			//1.创建对象，管理serversocket的对象

			NioEventLoopGroup bossGroup = new NioEventLoopGroup();

			NioEventLoopGroup workerGroup = new NioEventLoopGroup();

			ServerBootstrap serverBootstrap = new ServerBootstrap();
			//2.配置参数
			//链式编程
			serverBootstrap.group(bossGroup, workerGroup).
					channel(NioServerSocketChannel.class).
					childHandler(new ChannelInitializer<SocketChannel>() {

						@Override
						protected void initChannel(SocketChannel ch) throws Exception {
							//	在 Netty中把所有的业务逻辑处理 全部归总到了一个队列中
							//	这个队列中不包含了所有的处理逻辑，这些处理逻辑netty中有一个封装
							//	无锁化串行任务队列
							//	pipline
							ChannelPipeline pipeline = ch.pipeline();


							//	对于自定义协议的内容要进行编解码
							//解码:最大长度底层使用int的缓冲区来接受,信息头，每一个字段的长度（int是占四个字节）,添加字段的补偿值，从解码帧中去除的第一个字节数（一般用一个单位长度去套）
							pipeline.addLast(new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0, 4, 0, 4));

							//自定义编码器，int字段长度是4
							pipeline.addLast(new LengthFieldPrepender(4));

							//	实参处理
							pipeline.addLast("encoder", new ObjectEncoder());

							pipeline.addLast("decoder", new ObjectDecoder(Integer.MAX_VALUE, ClassResolvers.cacheDisabled(null)));

							//前面编解码是对数据的解析

							//最后一步是属于自己的逻辑
							//1.注册，对传过来的对象进行注册,给每一个对象起一个名字（名字是对外提供服务的名字）
							//2.服务位置登记
							//定义类执行的逻辑
							pipeline.addLast(new RegistryHandler());
						}
						//	128指定了最大selectorKey的数量
					}).option(ChannelOption.SO_BACKLOG, 128).
					childOption(ChannelOption.SO_KEEPALIVE, true);

			//正式启动服务，相当于使用一个死循环开始轮训
			ChannelFuture sync = serverBootstrap.bind(this.port).sync();
			System.out.println("my RPC Registry start listen at " + port);
			sync.channel().closeFuture().sync();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

	public static void main(String[] args) {
		new RpcRegistry(8080).start();
	}
}
